import Modeler from 'bpmn-js/lib/Modeler';
import { getBusinessObject, is } from 'bpmn-js/lib/util/ModelUtil';
import { FlowableExtension } from '@/pages/workflow/model/components/modeler/properties/FlowableExtension';
import customTranslateModule from './translate/CustomTranslate';

export class ModelerService {
  modeller: Modeler;
  element: any;
  businessObject: any;
  customerExtension: any;
  listenerExtension: any;
  listenerUrl: any;
  listenerExpression: any;

  init(container: string, flagSetter: any): void {
    this.modeller = new Modeler({
      container: container,
      additionalModules: [customTranslateModule],
      moddleExtensions: {
        flowable: FlowableExtension,
      },
    });

    // this.modeller.on('import.parse.complete', (event: any) => {
    // const rootElement = event.definitions.rootElements[0];
    // this.modeller.get('modeling').selectElements(rootElement);
    // this.selectedElement = rootElement;
    // this.selectedBusinessObject = getBusinessObject(this.selectedElement);
    // });

    this.modeller.on('element.click', (event: any) => {
      if (this.element === event.element) {
        return;
      }
      this.element = event.element;
      this.businessObject = getBusinessObject(this.element);

      this.ensureExtensions();
      this.customerExtension = this.getExtension('flowable:Extension');
      this.listenerExtension = this.getExtension('flowable:ExecutionListener');
      if (this.listenerExtension) {
        if (!this.listenerExtension.fields) {
          this.listenerExtension.fields = [];
        }
        let values = this.listenerExtension.fields.filter(
          (field: any) => field.name === 'url',
        );
        if (values.length > 0) {
          this.listenerUrl = values[0];
        }
        values = this.listenerExtension.fields.filter(
          (field: any) => field.name === 'expression',
        );
        if (values.length > 0) {
          this.listenerExpression = values[0];
        }
      }
      flagSetter?.((flag: boolean) => !flag);
    });
  }

  clean(): void {
    this.modeller = null;
    this.element = null;
    this.businessObject = null;
    this.customerExtension = null;
    this.listenerExtension = null;
    this.listenerUrl = null;
    this.listenerExpression = null;
  }

  is(types: string[]): boolean {
    return types.some((type) => is(this.element, type));
  }

  setProperty(key: string, value: any): void {
    const modeling = this.modeller.get('modeling');
    const property: any = {};
    property[key] = value;
    modeling.updateProperties(this.element, property);
  }

  setExtendArrayProperty(
    extend: string,
    extendKey: string,
    key: string,
    value: string,
  ): void {
    const factory = this.modeller.get('bpmnFactory');
    const property: any = {};
    property[key] = value;
    const ext = factory.create(extend, property);
    this.setProperty(extendKey, [ext]);
  }

  setExtendProperty(
    extend: string,
    extendKey: string,
    key: string,
    value: string,
  ): void {
    const factory = this.modeller.get('bpmnFactory');
    const property: any = {};
    property[key] = value;
    const ext = factory.create(extend, property);
    this.setProperty(extendKey, ext);
  }

  setCustomerExtensionElement(key: string, value: string): void {
    this.setExtensionElement('flowable:Extension', key, value);
  }

  // setListenerExtensionElement(event: string): void {
  //   if (event === '') {
  //     const geminiExtension = this.businessObject.extensions.values.filter(
  //       (extensionElement: any) => {
  //         return extensionElement.$instanceOf('flowable:ExecutionListener');
  //       },
  //     );
  //     geminiExtension.forEach((extension: any) => {
  //       const index = this.businessObject.extensions.values.indexOf(extension);
  //       this.businessObject.extensions.values.splice(index, 1);
  //     });
  //     this.updateExtensions();
  //   } else {
  //     this.setExtensionElement('flowable:ExecutionListener', 'event', event);
  //     this.setExtensionElement(
  //       'flowable:ExecutionListener',
  //       'class',
  //       'cn.geminis.workflow.service.service.engine.listener.RunRemoteExecutionListener',
  //     );
  //   }
  // }

  // setListenerField(name: string, expression: string): void {
  //   if (!this.listenerExtension.fields) {
  //     this.listenerExtension.fields = [];
  //   }
  //   const fieldValues = this.listenerExtension.fields.filter(
  //     (field: any) => field.name === name,
  //   );
  //   let fieldValue = fieldValues.length === 0 ? null : fieldValues[0];
  //   if (!fieldValue) {
  //     const provider = this.modeller.get('bpmnFactory');
  //     fieldValue = provider.create('flowable:Field');
  //     fieldValue.name = name;
  //     this.listenerExtension.fields.push(fieldValue);
  //   }
  //   fieldValue.expression = expression;
  //   this.updateExtensions();
  // }

  private setExtensionElement(type: string, key: string, value: string): void {
    let geminiExtension = this.getExtension(type);
    if (!geminiExtension) {
      const provider = this.modeller.get('bpmnFactory');
      geminiExtension = provider.create(type);
      this.businessObject.extensions.values.push(geminiExtension);
    }
    geminiExtension[key] = value;
    this.updateExtensions();
  }

  private ensureExtensions(): void {
    if (this.businessObject.extensionElements) {
      this.businessObject.extensions = this.businessObject.extensionElements;
    } else {
      const provider = this.modeller.get('bpmnFactory');
      this.businessObject.extensions = provider.create(
        'bpmn:ExtensionElements',
      );
    }
    if (!this.businessObject.extensions.values) {
      this.businessObject.extensions.values = [];
    }
  }

  private getExtension(type: string): any {
    const geminiExtension = this.businessObject.extensions.values.filter(
      (extensionElement: any) => {
        return extensionElement.$instanceOf(type);
      },
    );
    return geminiExtension.length === 0 ? null : geminiExtension[0];
  }

  private updateExtensions(): void {
    this.setProperty('extensionElements', this.businessObject.extensions);
  }
}
